home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
gnu
/
emacs
/
emacs1857
/
src_d2.zoo
/
source
/
lib+
/
alarm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-02
|
5KB
|
183 lines
#include <osbind.h>
#include <xbra.h>
#include <basepage.h>
#include <sysvars.h>
/**
** (sjk)++ This is a very cheap alarm() type call, when called with
** zero argument, turn off main body of interrupt code. When
** called with a positive argument, turn on interupt code,
** and start it counter to modify the variable echo_flag,
** when the counter expires. (set echo_flag = 1)
**/
static void timer __PROTO((void));
static void term __PROTO((void));
static void install_handlers __PROTO((void));
static void remove_handlers __PROTO((void));
static void unlink_handler __PROTO((xbra_struct *me, int exc));
static void install_timer __PROTO((void));
void install_alarm __PROTO((void));
extern BASEPAGE *_base;
static BASEPAGE **act_pd;
static BASEPAGE *my_base;
static short installed = 0;
extern int echo_flag;
long int t_ms;
long int enabled;
/* XBRA pointers to our new interupt handlers, 1. timer for alarm */
/* 2. term - remove */
/* handlers. */
static xbra_struct timer_xbra = _XBRA_INIT(timer);
static xbra_struct term_xbra = _XBRA_INIT(term);
void install_alarm()
{
long *sysbase;
sysbase = (long *) get_sysvar((void *) _sysbase);
switch (sysbase[6])
{ case 0x11201985L:
case 0x02061986L:
case 0x04241986L:
act_pd = (BASEPAGE **) 0x602C;
break;
default:
act_pd = (BASEPAGE **) sysbase[10];
}
(void) install_timer();
}
/* use the Xbra convention to link into the evnt_timer loop (20ms) */
/* use the Xbra convention to link into the terminate handler. */
void install_timer()
{
timer_xbra.next = (xptr) Setexc(0x100, _XBRA_VEC(timer_xbra));
term_xbra.next = (xptr) Setexc(0x102, _XBRA_VEC(term_xbra));
my_base = (BASEPAGE *)_base;
}
/* call unlink to remove our hooked interupt handlers. */
void remove_handlers()
{ if (_base == *act_pd)
{
if (_base != my_base)
_base -= 2;
else
{
unlink_handler(&timer_xbra,0x100);
unlink_handler(&term_xbra,0x102);
installed = 0;
}
}
}
/*
* unlink a handler in a xbra friendly manner from the exc chain
*/
static void unlink_handler(me, exc)
xbra_struct *me;
int exc;
{
xbra_struct *this, *prev;
long save_ssp;
unsigned long ulong;
ulong = (unsigned long)Setexc(exc,-1L);
this = (struct __xbra *)(ulong - 12L );
if(this == me)
{ /* at the head, just unlink */
Setexc(exc, me->next);
return;
}
/* otherwise find me in the chain and unlink */
save_ssp = Super(0L);
for(prev = this; this && (this != me); prev = this, this = this->next)
{
/* validate the xbra */
if(this->xbra_magic != _XBRA_MAGIC)
{ /* shame on you */
Super(save_ssp);
Setexc(exc, me->next); /* nuke it, otherwise it may call ME */
return; /* after i am deinstalled */
}
}
if(this == me)
{ /* unlink me from middle of the chain */
prev->next = this->next;
Super(save_ssp);
return;
}
/* we are screwed */
Super(save_ssp);
Cconws("\r\nwhat the fuck!\r\n\n");
}
void my_alarm(time)
int time;
{ if (!installed)
{ install_alarm();
installed = 1;
}
if (time == 0)
enabled = 0;
else
{ t_ms = 50*time;
enabled = 1;
}
}
static void term()
{
if (_base != *act_pd)
{ __asm__ volatile("\
unlk a6
jmp %0@"
:
: "a"(term_xbra.next));
}
if (installed)
remove_handlers();
__asm__ volatile("\
unlk a6
jmp %0@"
:
: "a"(term_xbra.next));
}
/*
* timer handler
* in etv_timer timer handoff vector chain (called every 4th tick)
* stack at this point:
* <exception frame user pc, sr> 2
* <saved d0-d7/a0-a6> 60
* <timer calibration .w> 2
* <return address to timer C intr routine> 4
* ---
* 68 (offset to user pc)
*/
__asm__ ("\
.text; .even
_timer:
tstl _enabled /* is it zero ? */
beq 1f /* No! We have something to do. */
subql #1,_t_ms /* Decrement our timer... */
bne 1f /* It is not out time! */
movl #0,_enabled /* disbale us. */
movl #1,_echo_flag /* our whole goal. */
1:
movl _timer_xbra+8,sp@- /* call next handler in chain */
rts ");